{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Python绘制桑基图分析广告转化数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "桑基图 (Sankey Diagram)：是一种特定类型的流图，用于描述一组值到另一组值的流向。\n",
    "\n",
    "桑基图的特点如下：\n",
    "* 起始流量和结束流量相同，所有主支宽度的总和与所有分出去的分支宽度总和相等，保持能量的平衡；\n",
    "* 在内部，不同的线条代表了不同的流量分流情况，它的宽度成比例地显示此分支占有的流量；\n",
    "* 节点不同的宽度代表了特定状态下的流量大小。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 读取广告转化数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数据源：https://www.kaggle.com/loveall/clicks-conversion-tracking/data\n",
    "# 广告转化数据集：Ad Conversions Data\n",
    "df = pd.read_csv(\"./datas/KAG_conversion_data.csv\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ad_id</th>\n",
       "      <th>xyz_campaign_id</th>\n",
       "      <th>fb_campaign_id</th>\n",
       "      <th>age</th>\n",
       "      <th>gender</th>\n",
       "      <th>interest</th>\n",
       "      <th>Impressions</th>\n",
       "      <th>Clicks</th>\n",
       "      <th>Spent</th>\n",
       "      <th>Total_Conversion</th>\n",
       "      <th>Approved_Conversion</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>708746</td>\n",
       "      <td>916</td>\n",
       "      <td>103916</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>15</td>\n",
       "      <td>7350</td>\n",
       "      <td>1</td>\n",
       "      <td>1.43</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>708749</td>\n",
       "      <td>916</td>\n",
       "      <td>103917</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>16</td>\n",
       "      <td>17861</td>\n",
       "      <td>2</td>\n",
       "      <td>1.82</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>708771</td>\n",
       "      <td>916</td>\n",
       "      <td>103920</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>20</td>\n",
       "      <td>693</td>\n",
       "      <td>0</td>\n",
       "      <td>0.00</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>708815</td>\n",
       "      <td>916</td>\n",
       "      <td>103928</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>28</td>\n",
       "      <td>4259</td>\n",
       "      <td>1</td>\n",
       "      <td>1.25</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>708818</td>\n",
       "      <td>916</td>\n",
       "      <td>103928</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>28</td>\n",
       "      <td>4133</td>\n",
       "      <td>1</td>\n",
       "      <td>1.29</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>708820</td>\n",
       "      <td>916</td>\n",
       "      <td>103929</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>29</td>\n",
       "      <td>1915</td>\n",
       "      <td>0</td>\n",
       "      <td>0.00</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>708889</td>\n",
       "      <td>916</td>\n",
       "      <td>103940</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>15</td>\n",
       "      <td>15615</td>\n",
       "      <td>3</td>\n",
       "      <td>4.77</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>708895</td>\n",
       "      <td>916</td>\n",
       "      <td>103941</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>16</td>\n",
       "      <td>10951</td>\n",
       "      <td>1</td>\n",
       "      <td>1.27</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>708953</td>\n",
       "      <td>916</td>\n",
       "      <td>103951</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>27</td>\n",
       "      <td>2355</td>\n",
       "      <td>1</td>\n",
       "      <td>1.50</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>708958</td>\n",
       "      <td>916</td>\n",
       "      <td>103952</td>\n",
       "      <td>30-34</td>\n",
       "      <td>M</td>\n",
       "      <td>28</td>\n",
       "      <td>9502</td>\n",
       "      <td>3</td>\n",
       "      <td>3.16</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    ad_id  xyz_campaign_id  fb_campaign_id    age gender  interest  \\\n",
       "0  708746              916          103916  30-34      M        15   \n",
       "1  708749              916          103917  30-34      M        16   \n",
       "2  708771              916          103920  30-34      M        20   \n",
       "3  708815              916          103928  30-34      M        28   \n",
       "4  708818              916          103928  30-34      M        28   \n",
       "5  708820              916          103929  30-34      M        29   \n",
       "6  708889              916          103940  30-34      M        15   \n",
       "7  708895              916          103941  30-34      M        16   \n",
       "8  708953              916          103951  30-34      M        27   \n",
       "9  708958              916          103952  30-34      M        28   \n",
       "\n",
       "   Impressions  Clicks  Spent  Total_Conversion  Approved_Conversion  \n",
       "0         7350       1   1.43                 2                    1  \n",
       "1        17861       2   1.82                 2                    0  \n",
       "2          693       0   0.00                 1                    0  \n",
       "3         4259       1   1.25                 1                    0  \n",
       "4         4133       1   1.29                 1                    1  \n",
       "5         1915       0   0.00                 1                    1  \n",
       "6        15615       3   4.77                 1                    0  \n",
       "7        10951       1   1.27                 1                    1  \n",
       "8         2355       1   1.50                 1                    0  \n",
       "9         9502       3   3.16                 1                    0  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "绘图目的：\n",
    "总流量 > 不同的活动 > 性别 > 年龄"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 构造桑基图数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数据处理\n",
    "df[\"total\"] = \"全量\"\n",
    "df[\"xyz_campaign_id\"] = df[\"xyz_campaign_id\"].map(lambda x : f\"campaign_{x}\")\n",
    "df[\"gender\"] = df[\"gender\"].map(lambda x : f\"gender_{x}\")\n",
    "df[\"age\"] = df[\"age\"].map(lambda x : f\"age_{x}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['全量', 'campaign_916', 'campaign_936', 'campaign_1178', 'age_30-34',\n",
       "       'age_35-39', 'age_40-44', 'age_45-49', 'gender_M', 'gender_F'],\n",
       "      dtype=object)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Pyecharts桑基图数据1：节点列表\n",
    "nodes = pd.concat([df[\"total\"], df[\"xyz_campaign_id\"], df[\"age\"], df[\"gender\"]]).unique()\n",
    "nodes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total xyz_campaign_id\n",
      "xyz_campaign_id gender\n",
      "gender age\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[['全量', 'campaign_1178', 625],\n",
       " ['全量', 'campaign_916', 54],\n",
       " ['全量', 'campaign_936', 464],\n",
       " ['campaign_1178', 'gender_F', 276],\n",
       " ['campaign_1178', 'gender_M', 349],\n",
       " ['campaign_916', 'gender_F', 19],\n",
       " ['campaign_916', 'gender_M', 35],\n",
       " ['campaign_936', 'gender_F', 256],\n",
       " ['campaign_936', 'gender_M', 208],\n",
       " ['gender_F', 'age_30-34', 197],\n",
       " ['gender_F', 'age_35-39', 109],\n",
       " ['gender_F', 'age_40-44', 107],\n",
       " ['gender_F', 'age_45-49', 138],\n",
       " ['gender_M', 'age_30-34', 229],\n",
       " ['gender_M', 'age_35-39', 139],\n",
       " ['gender_M', 'age_40-44', 103],\n",
       " ['gender_M', 'age_45-49', 121]]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Pyecharts桑基图数据2：节点到达关系列表\n",
    "type_list = [\"total\", \"xyz_campaign_id\", \"gender\", \"age\"]\n",
    "from_to_list = []\n",
    "for idx in range(len(type_list)-1):\n",
    "    from_type = type_list[idx]\n",
    "    to_type = type_list[idx+1]\n",
    "    print(from_type, to_type)\n",
    "    \n",
    "    df_agg = df.groupby([from_type, to_type]).size().reset_index()\n",
    "    df_agg.columns = [\"from\", \"to\", \"value\"]\n",
    "\n",
    "    for _, (from_key, to_key, value) in df_agg.iterrows():\n",
    "        from_to_list.append([from_key, to_key, value])\n",
    "\n",
    "from_to_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>from</th>\n",
       "      <th>to</th>\n",
       "      <th>value</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>全量</td>\n",
       "      <td>campaign_1178</td>\n",
       "      <td>625</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>全量</td>\n",
       "      <td>campaign_916</td>\n",
       "      <td>54</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>全量</td>\n",
       "      <td>campaign_936</td>\n",
       "      <td>464</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  from             to  value\n",
       "0   全量  campaign_1178    625\n",
       "1   全量   campaign_916     54\n",
       "2   全量   campaign_936    464"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 中间步骤的解释：计算相邻节点的from和to\n",
    "df_agg = df.groupby([\"total\", \"xyz_campaign_id\"]).size().reset_index()\n",
    "df_agg.columns = [\"from\", \"to\", \"value\"]\n",
    "\n",
    "df_agg"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. 绘制桑基图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'name': '全量'},\n",
       " {'name': 'campaign_916'},\n",
       " {'name': 'campaign_936'},\n",
       " {'name': 'campaign_1178'},\n",
       " {'name': 'age_30-34'},\n",
       " {'name': 'age_35-39'},\n",
       " {'name': 'age_40-44'},\n",
       " {'name': 'age_45-49'},\n",
       " {'name': 'gender_M'},\n",
       " {'name': 'gender_F'}]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1. 转换节点列表为桑基图形式\n",
    "pyecharts_nodes = [{\"name\": node} for node in nodes]\n",
    "pyecharts_nodes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'source': '全量', 'target': 'campaign_1178', 'value': 625},\n",
       " {'source': '全量', 'target': 'campaign_916', 'value': 54},\n",
       " {'source': '全量', 'target': 'campaign_936', 'value': 464},\n",
       " {'source': 'campaign_1178', 'target': 'gender_F', 'value': 276},\n",
       " {'source': 'campaign_1178', 'target': 'gender_M', 'value': 349},\n",
       " {'source': 'campaign_916', 'target': 'gender_F', 'value': 19},\n",
       " {'source': 'campaign_916', 'target': 'gender_M', 'value': 35},\n",
       " {'source': 'campaign_936', 'target': 'gender_F', 'value': 256},\n",
       " {'source': 'campaign_936', 'target': 'gender_M', 'value': 208},\n",
       " {'source': 'gender_F', 'target': 'age_30-34', 'value': 197},\n",
       " {'source': 'gender_F', 'target': 'age_35-39', 'value': 109},\n",
       " {'source': 'gender_F', 'target': 'age_40-44', 'value': 107},\n",
       " {'source': 'gender_F', 'target': 'age_45-49', 'value': 138},\n",
       " {'source': 'gender_M', 'target': 'age_30-34', 'value': 229},\n",
       " {'source': 'gender_M', 'target': 'age_35-39', 'value': 139},\n",
       " {'source': 'gender_M', 'target': 'age_40-44', 'value': 103},\n",
       " {'source': 'gender_M', 'target': 'age_45-49', 'value': 121}]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2. 转换跳转列表为桑基图形式\n",
    "pyecharts_links = [\n",
    "            {\"source\": source, \"target\": target, \"value\": value}\n",
    "            for source, target, value in from_to_list\n",
    "        ]\n",
    "pyecharts_links"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<script>\n",
       "    require.config({\n",
       "        paths: {\n",
       "            'echarts':'https://assets.pyecharts.org/assets/echarts.min'\n",
       "        }\n",
       "    });\n",
       "</script>\n",
       "\n",
       "        <div id=\"36b77001aeaa4f8b8058315a4222572c\" style=\"width:900px; height:500px;\"></div>\n",
       "\n",
       "<script>\n",
       "        require(['echarts'], function(echarts) {\n",
       "                var chart_36b77001aeaa4f8b8058315a4222572c = echarts.init(\n",
       "                    document.getElementById('36b77001aeaa4f8b8058315a4222572c'), 'white', {renderer: 'canvas'});\n",
       "                var option_36b77001aeaa4f8b8058315a4222572c = {\n",
       "    \"animation\": true,\n",
       "    \"animationThreshold\": 2000,\n",
       "    \"animationDuration\": 1000,\n",
       "    \"animationEasing\": \"cubicOut\",\n",
       "    \"animationDelay\": 0,\n",
       "    \"animationDurationUpdate\": 300,\n",
       "    \"animationEasingUpdate\": \"cubicOut\",\n",
       "    \"animationDelayUpdate\": 0,\n",
       "    \"color\": [\n",
       "        \"#c23531\",\n",
       "        \"#2f4554\",\n",
       "        \"#61a0a8\",\n",
       "        \"#d48265\",\n",
       "        \"#749f83\",\n",
       "        \"#ca8622\",\n",
       "        \"#bda29a\",\n",
       "        \"#6e7074\",\n",
       "        \"#546570\",\n",
       "        \"#c4ccd3\",\n",
       "        \"#f05b72\",\n",
       "        \"#ef5b9c\",\n",
       "        \"#f47920\",\n",
       "        \"#905a3d\",\n",
       "        \"#fab27b\",\n",
       "        \"#2a5caa\",\n",
       "        \"#444693\",\n",
       "        \"#726930\",\n",
       "        \"#b2d235\",\n",
       "        \"#6d8346\",\n",
       "        \"#ac6767\",\n",
       "        \"#1d953f\",\n",
       "        \"#6950a1\",\n",
       "        \"#918597\"\n",
       "    ],\n",
       "    \"series\": [\n",
       "        {\n",
       "            \"type\": \"sankey\",\n",
       "            \"data\": [\n",
       "                {\n",
       "                    \"name\": \"\\u5168\\u91cf\"\n",
       "                },\n",
       "                {\n",
       "                    \"name\": \"campaign_916\"\n",
       "                },\n",
       "                {\n",
       "                    \"name\": \"campaign_936\"\n",
       "                },\n",
       "                {\n",
       "                    \"name\": \"campaign_1178\"\n",
       "                },\n",
       "                {\n",
       "                    \"name\": \"age_30-34\"\n",
       "                },\n",
       "                {\n",
       "                    \"name\": \"age_35-39\"\n",
       "                },\n",
       "                {\n",
       "                    \"name\": \"age_40-44\"\n",
       "                },\n",
       "                {\n",
       "                    \"name\": \"age_45-49\"\n",
       "                },\n",
       "                {\n",
       "                    \"name\": \"gender_M\"\n",
       "                },\n",
       "                {\n",
       "                    \"name\": \"gender_F\"\n",
       "                }\n",
       "            ],\n",
       "            \"links\": [\n",
       "                {\n",
       "                    \"source\": \"\\u5168\\u91cf\",\n",
       "                    \"target\": \"campaign_1178\",\n",
       "                    \"value\": 625\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"\\u5168\\u91cf\",\n",
       "                    \"target\": \"campaign_916\",\n",
       "                    \"value\": 54\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"\\u5168\\u91cf\",\n",
       "                    \"target\": \"campaign_936\",\n",
       "                    \"value\": 464\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"campaign_1178\",\n",
       "                    \"target\": \"gender_F\",\n",
       "                    \"value\": 276\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"campaign_1178\",\n",
       "                    \"target\": \"gender_M\",\n",
       "                    \"value\": 349\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"campaign_916\",\n",
       "                    \"target\": \"gender_F\",\n",
       "                    \"value\": 19\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"campaign_916\",\n",
       "                    \"target\": \"gender_M\",\n",
       "                    \"value\": 35\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"campaign_936\",\n",
       "                    \"target\": \"gender_F\",\n",
       "                    \"value\": 256\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"campaign_936\",\n",
       "                    \"target\": \"gender_M\",\n",
       "                    \"value\": 208\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"gender_F\",\n",
       "                    \"target\": \"age_30-34\",\n",
       "                    \"value\": 197\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"gender_F\",\n",
       "                    \"target\": \"age_35-39\",\n",
       "                    \"value\": 109\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"gender_F\",\n",
       "                    \"target\": \"age_40-44\",\n",
       "                    \"value\": 107\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"gender_F\",\n",
       "                    \"target\": \"age_45-49\",\n",
       "                    \"value\": 138\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"gender_M\",\n",
       "                    \"target\": \"age_30-34\",\n",
       "                    \"value\": 229\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"gender_M\",\n",
       "                    \"target\": \"age_35-39\",\n",
       "                    \"value\": 139\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"gender_M\",\n",
       "                    \"target\": \"age_40-44\",\n",
       "                    \"value\": 103\n",
       "                },\n",
       "                {\n",
       "                    \"source\": \"gender_M\",\n",
       "                    \"target\": \"age_45-49\",\n",
       "                    \"value\": 121\n",
       "                }\n",
       "            ],\n",
       "            \"left\": \"5%\",\n",
       "            \"top\": \"5%\",\n",
       "            \"right\": \"20%\",\n",
       "            \"bottom\": \"5%\",\n",
       "            \"nodeWidth\": 20,\n",
       "            \"nodeGap\": 8,\n",
       "            \"nodeAlign\": \"justify\",\n",
       "            \"layoutIteration\": 32,\n",
       "            \"orient\": \"horizontal\",\n",
       "            \"draggable\": true,\n",
       "            \"focusNodeAdjacency\": false,\n",
       "            \"label\": {\n",
       "                \"show\": true,\n",
       "                \"position\": \"right\",\n",
       "                \"margin\": 8\n",
       "            },\n",
       "            \"lineStyle\": {\n",
       "                \"show\": true,\n",
       "                \"width\": 1,\n",
       "                \"opacity\": 0.2,\n",
       "                \"curveness\": 0.5,\n",
       "                \"type\": \"solid\",\n",
       "                \"color\": \"source\"\n",
       "            }\n",
       "        }\n",
       "    ],\n",
       "    \"legend\": [\n",
       "        {\n",
       "            \"data\": [\n",
       "                \"\"\n",
       "            ],\n",
       "            \"selected\": {\n",
       "                \"\": true\n",
       "            },\n",
       "            \"show\": true,\n",
       "            \"padding\": 5,\n",
       "            \"itemGap\": 10,\n",
       "            \"itemWidth\": 25,\n",
       "            \"itemHeight\": 14\n",
       "        }\n",
       "    ],\n",
       "    \"tooltip\": {\n",
       "        \"show\": true,\n",
       "        \"trigger\": \"item\",\n",
       "        \"triggerOn\": \"mousemove|click\",\n",
       "        \"axisPointer\": {\n",
       "            \"type\": \"line\"\n",
       "        },\n",
       "        \"textStyle\": {\n",
       "            \"fontSize\": 14\n",
       "        },\n",
       "        \"borderWidth\": 0\n",
       "    },\n",
       "    \"title\": [\n",
       "        {\n",
       "            \"text\": \"\\u5e7f\\u544a\\u6548\\u679c\\u6851\\u57fa\\u56fe\",\n",
       "            \"padding\": 5,\n",
       "            \"itemGap\": 10\n",
       "        }\n",
       "    ]\n",
       "};\n",
       "                chart_36b77001aeaa4f8b8058315a4222572c.setOption(option_36b77001aeaa4f8b8058315a4222572c);\n",
       "        });\n",
       "    </script>\n"
      ],
      "text/plain": [
       "<pyecharts.render.display.HTML at 0x220a92e3508>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pyecharts import options as opts\n",
    "from pyecharts.charts import Sankey\n",
    "\n",
    "sankey = (\n",
    "    Sankey()\n",
    "    .add(\n",
    "        \"\",\n",
    "        pyecharts_nodes,\n",
    "        pyecharts_links,\n",
    "        linestyle_opt=opts.LineStyleOpts(opacity=0.2, curve=0.5, color=\"source\"),\n",
    "        label_opts=opts.LabelOpts(position=\"right\"),\n",
    "    )\n",
    "    .set_global_opts(title_opts=opts.TitleOpts(title=\"广告效果桑基图\"))\n",
    ")\n",
    "\n",
    "sankey.render_notebook()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
